package com.bdbit.ChargingStation.services.impl;

import com.bdbit.ChargingStation.Utils.TimeUtils;
import com.bdbit.ChargingStation.dao.ChargingOrderDao;
import com.bdbit.ChargingStation.dao.mapper.OrderEntityMapper;
import com.bdbit.ChargingStation.entity.*;
import com.bdbit.ChargingStation.services.ChargingOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.bdbit.ChargingStation.services.DeviceOrderService;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;

@Slf4j
@Service
public class ChargingOrderServiceImpl implements ChargingOrderService {

    private final ChargingOrderDao chargingOrderDao;
    @Autowired
    JdbcTemplate jct;

    @Autowired
    OrderEntityMapper orderEntityMapper;

    // 北京时区
    private static final ZoneId BEIJING_ZONE = ZoneId.of("Asia/Shanghai");
    // 定义状态常量（替代原ChargingOrder常量）
    // 移除重复的状态常量定义，使用OrderEntity中的统一定义
    // 删除以下行：
    // public static final int STATUS_UNPAID = 0;
    // public static final int STATUS_IN_PROGRESS = 1;
    // public static final int STATUS_COMPLETED = 2;
    // public static final int STATUS_REFUNDED = 3;
    // 定义日期格式对象 - 解决图片中的错误
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    public ChargingOrderServiceImpl(ChargingOrderDao chargingOrderDao) {
        this.chargingOrderDao = chargingOrderDao;
    }

    // 获取当前北京时间
    private Date getCurrentBeijingTime() {
        return Date.from(LocalDateTime.now().atZone(BEIJING_ZONE).toInstant());
    }

    @Override
    @Transactional
    public ChargingOrder createOrder(ChargingOrder order) {
        // 验证必要字段
        if (order.getUserId() == null || order.getUserId().isEmpty()) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (order.getEleCode() == null || order.getEleCode().isEmpty()) {
            throw new IllegalArgumentException("电桩号不能为空");
        }
        if (order.getRegionCode() == null || order.getRegionCode().isEmpty()) {
            throw new IllegalArgumentException("区域编码不能为空");
        }
        // 设置默认值
        order.setStatus(0); // 0-未支付
        order.setCreateDate(new Date());
        order.setUpdateDate(new Date());
        order.setIsDeleted(0);

        // 设置 orderYearMonth
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        order.setOrderYearMonth(sdf.format(new Date()));

        // 确保预付金额不为空
        if (order.getPrepayAmount() == null) {
            order.setPrepayAmount(BigDecimal.ZERO);
        }

        // 清除前端可能传递的时间字段
        order.setStartTime(null);
        order.setEndTime(null);
        order.setDeviceStartTime(null);
        order.setDeviceEndTime(null);
        order.setPaymentTime(null);
        order.setRefundTime(null);

        // 计算总金额
        if (order.getChargingKwh() != null && order.getUnitPrice() != null) {
            BigDecimal total = order.getChargingKwh().multiply(order.getUnitPrice());
            order.setTotalAmount(total);
        } else {
            order.setTotalAmount(BigDecimal.ZERO);
        }

        chargingOrderDao.insert(order);
        return order;
    }

    @Override
    @Transactional
    public ChargingOrder updateOrder(ChargingOrder order) {
        // 从数据库获取现有订单
        ChargingOrder existingOrder = chargingOrderDao.findById(order.getId());
        if (existingOrder == null) {
            throw new RuntimeException("订单不存在");
        }

        // 保留不应修改的字段
        order.setOrderYearMonth(existingOrder.getOrderYearMonth());
        order.setCreateDate(existingOrder.getCreateDate());
        order.setIsDeleted(existingOrder.getIsDeleted());

        // 设置更新时间
        order.setUpdateDate(new Date());

        // 确保预付金额不为空
        if (order.getPrepayAmount() == null) {
            // 使用现有值
            order.setPrepayAmount(existingOrder.getPrepayAmount());
        }

        // 清除前端可能传递的时间字段
        order.setStartTime(null);
        order.setEndTime(null);
        order.setDeviceStartTime(null);
        order.setDeviceEndTime(null);
        order.setPaymentTime(null);
        order.setRefundTime(null);

        // 计算总金额
        if (order.getChargingKwh() != null && order.getUnitPrice() != null) {
            BigDecimal total = order.getChargingKwh().multiply(order.getUnitPrice());
            order.setTotalAmount(total);
        } else {
            // 如果未提供充电量或单价，使用原值
            order.setChargingKwh(existingOrder.getChargingKwh());
            order.setUnitPrice(existingOrder.getUnitPrice());
            order.setTotalAmount(existingOrder.getTotalAmount());
        }

        chargingOrderDao.update(order);
        return order;
    }

    @Autowired
    private DeviceOrderService deviceOrderService;

    @Override
    @Transactional
    public void deleteOrder(Long id) {
        // 逻辑删除而非物理删除
        ChargingOrder order = chargingOrderDao.findById(id);
        if (order != null) {
            // 清理设备映射关系
            if (order.getEleCode() != null) {
                deviceOrderService.unbindDevice(order.getEleCode());
                log.info("删除订单时清理设备映射: eleCode={}, orderId={}", order.getEleCode(), id);
            }
            
            order.setIsDeleted(1);
            order.setUpdateDate(getCurrentBeijingTime());
            chargingOrderDao.update(order);
        }
    }

    @Override
    public ChargingOrder getOrderById(Long id) {
        return chargingOrderDao.findById(id);
    }

    @Override
    public List<ChargingOrder> getAllOrders(String startDateStr, String endDateStr) {
        try {
            // 解决图片中的错误：使用正确的 parseDate 方法
            Date startDate = parseDate(startDateStr);
            Date endDate = parseDate(endDateStr);

            // 验证日期范围
            if (startDate != null && endDate != null && startDate.after(endDate)) {
                throw new IllegalArgumentException("开始日期不能晚于结束日期");
            }

            // 设置时间范围
            Date startOfDay = getStartOfDay(startDate);
            Date endOfDay = getEndOfDay(endDate);

            return chargingOrderDao.findAllWithDateRange(startOfDay, endOfDay);
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式不正确，请使用 yyyy-MM-dd 格式");
        }
    }

    @Override
    public List<ChargingOrder> getOrdersByUser(String userId, String startDateStr, String endDateStr) {
        try {
            // 解决图片中的错误：使用正确的 parseDate 方法
            Date startDate = parseDate(startDateStr);
            Date endDate = parseDate(endDateStr);

            // 验证日期范围
            if (startDate != null && endDate != null && startDate.after(endDate)) {
                throw new IllegalArgumentException("开始日期不能晚于结束日期");
            }

            // 设置时间范围
            Date startOfDay = getStartOfDay(startDate);
            Date endOfDay = getEndOfDay(endDate);

            return chargingOrderDao.findByUserIdWithDateRange(userId, startOfDay, endOfDay);
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式不正确，请使用 yyyy-MM-dd 格式");
        }
    }

    @Override
    public List<ChargingOrder> getOrdersByStatus(Integer status, String startDateStr, String endDateStr) {
        try {
            // 解决图片中的错误：使用正确的 parseDate 方法
            Date startDate = parseDate(startDateStr);
            Date endDate = parseDate(endDateStr);

            // 验证日期范围
            if (startDate != null && endDate != null && startDate.after(endDate)) {
                throw new IllegalArgumentException("开始日期不能晚于结束日期");
            }

            // 设置时间范围
            Date startOfDay = getStartOfDay(startDate);
            Date endOfDay = getEndOfDay(endDate);

            return chargingOrderDao.findByStatusWithDateRange(status, startOfDay, endOfDay);
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式不正确，请使用 yyyy-MM-dd 格式");
        }
    }

    @Override
    public void completeOrder(String orderId) {

    }

    @Override
    public void completeOrder(Long orderId) {
        try {
            // 转换为字符串调用已有方法
            completeOrder(String.valueOf(orderId));
        } catch (Exception e) {
            throw new RuntimeException("完成订单失败: " + e.getMessage(), e);
        }
    }

    // 以下方法保持不变，但会调用带时间筛选的方法
    @Override
    public List<ChargingOrder> getAllOrders() {
        return getAllOrders(null, null);
    }

    @Override
    public List<ChargingOrder> getOrdersByUser(String userId) {
        return getOrdersByUser(userId, null, null);
    }

    @Override
    public List<ChargingOrder> getOrdersByStatus(Integer status) {
        return getOrdersByStatus(status, null, null);
    }

    @Override
    @Transactional
    public ChargingOrder startCharging(Long orderId) {
        ChargingOrder order = chargingOrderDao.findById(orderId);
        if (order != null && order.getStatus() == 0) { // 未支付状态
            order.setStatus(1); // 进行中
            order.setStartTime(getCurrentBeijingTime()); // 在这里设置充电开始时间
            order.setDeviceStartTime(getCurrentBeijingTime());
            order.setUpdateDate(getCurrentBeijingTime());
            chargingOrderDao.update(order);
        }
        return order;
    }

    @Override
    @Transactional
    public ChargingOrder stopCharging(Long orderId) {
        ChargingOrder order = chargingOrderDao.findById(orderId);
        if (order != null && order.getStatus() == 1) { // 进行中状态
            order.setStatus(2); // 已完成
            order.setEndTime(getCurrentBeijingTime());
            order.setDeviceEndTime(getCurrentBeijingTime());
            order.setUpdateDate(getCurrentBeijingTime());

            // 计算实际充电时长
            if (order.getStartTime() != null && order.getEndTime() != null) {
                long duration = (order.getEndTime().getTime() - order.getStartTime().getTime()) / (1000 * 60);
                order.setReportedDuration((int) duration);
            }

            // 计算实际金额
            if (order.getChargingKwh() != null && order.getUnitPrice() != null) {
                BigDecimal actualAmount = order.getChargingKwh().multiply(order.getUnitPrice());
                order.setTotalAmount(actualAmount);

                // 计算退款金额
                if (order.getPrepayAmount() != null && actualAmount.compareTo(order.getPrepayAmount()) < 0) {
                    order.setRefundAmount(order.getPrepayAmount().subtract(actualAmount));
                }
            }

            chargingOrderDao.update(order);
        }
        return order;
    }

    @Override
    @Transactional
    public ChargingOrder processRefund(Long orderId) {
        ChargingOrder order = chargingOrderDao.findById(orderId);
        if (order != null && order.getStatus() == 2 && // 已完成
                order.getRefundAmount() != null && order.getRefundAmount().compareTo(BigDecimal.ZERO) > 0) {

            order.setStatus(3); // 已退款
            order.setRefundTime(getCurrentBeijingTime());
            order.setUpdateDate(getCurrentBeijingTime());
            chargingOrderDao.update(order);
        }
        return order;
    }

    @Override
    public List<ChargingOrder> getActiveOrders() {
        return chargingOrderDao.findActiveOrders();
    }

    // 获取一天的开始时间（00:00:00）
    private Date getStartOfDay(Date date) {
        if (date == null) return null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    // 获取一天的结束时间（23:59:59）
    private Date getEndOfDay(Date date) {
        if (date == null) return null;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    // 解析日期字符串 - 修复图片中的错误
    private Date parseDate(String dateStr) throws ParseException {
        if (!StringUtils.hasText(dateStr)) {
            return null;
        }
        return DATE_FORMAT.parse(dateStr);
    }

    @Override
    public PageResult<ChargingOrder> searchOrders(
            String userId, Integer status, String regionCode, String eleCode,
            String startDateStr, String endDateStr, int page, int size) {

        Map<String, Object> params = new HashMap<>();
        if (StringUtils.hasText(userId)) params.put("userId", userId);
        if (status != null) params.put("status", status);
        if (StringUtils.hasText(regionCode)) params.put("regionCode", regionCode);
        if (StringUtils.hasText(eleCode)) params.put("eleCode", eleCode);

        // 处理日期参数
        try {
            if (StringUtils.hasText(startDateStr)) {
                params.put("startDate", parseDate(startDateStr));
            }
            if (StringUtils.hasText(endDateStr)) {
                // 结束日期设置为当天的最后一秒
                Date endDate = parseDate(endDateStr);
                if (endDate != null) {
                    params.put("endDate", getEndOfDay(endDate));
                }
            }
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式不正确");
        }

        // 添加分页参数
        int offset = page * size;
        params.put("offset", offset);
        params.put("size", size);

        // 执行XML查询
        List<ChargingOrder> orders = chargingOrderDao.searchOrders(params);
        long total = chargingOrderDao.countSearchOrders(params);

        return new PageResult<>(orders, total);
    }

    @Override
    public PageResult<ChargingOrder> searchOrders(
            String userId, Integer status, String regionCode, String eleCode,
            LocalDate startDate, LocalDate endDate, int page, int size) {

        Map<String, Object> params = new HashMap<>();
        if (StringUtils.hasText(userId)) params.put("userId", userId);
        if (status != null) params.put("status", status);
        if (StringUtils.hasText(regionCode)) params.put("regionCode", regionCode);
        if (StringUtils.hasText(eleCode)) params.put("eleCode", eleCode);

        // 处理日期参数 - 转换为北京时间
        try {
            if (startDate != null) {
                // 开始日期设置为当天的开始时间
                ZonedDateTime startZdt = startDate.atStartOfDay(BEIJING_ZONE);
                params.put("startDate", Date.from(startZdt.toInstant()));
            }

            if (endDate != null) {
                // 结束日期设置为当天的最后一秒
                ZonedDateTime endZdt = endDate.atTime(23, 59, 59).atZone(BEIJING_ZONE);
                params.put("endDate", Date.from(endZdt.toInstant()));
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("日期处理错误: " + e.getMessage());
        }

        // 添加分页参数
        int offset = page * size;
        params.put("offset", offset);
        params.put("size", size);

        // 执行XML查询
        List<ChargingOrder> orders = chargingOrderDao.searchOrders(params);
        long total = chargingOrderDao.countSearchOrders(params);

        return new PageResult<>(orders, total);
    }

    @Override
    public Integer getOrderstatusbyid(Long id) {
        ChargingOrder order = chargingOrderDao.findById(id);
        return (order != null && order.getIsDeleted() == 0) ? order.getStatus() : null;
    }

    @Override
    public OrderEntity updateOrderStatus2(String orderId, Integer status) {
        try {
            // 1. 验证订单是否存在
            String selectSql = "SELECT * FROM charging_order WHERE id = ?";
            OrderEntity order = jct.queryForObject(
                    selectSql,
                    new Object[]{orderId},
                    new BeanPropertyRowMapper<>(OrderEntity.class)
            );

            if (order == null) {
                throw new IllegalArgumentException("订单不存在: " + orderId);
            }

            // 2. 更新订单状态
            String updateSql = "UPDATE charging_order SET status = ?, update_date = ? WHERE id = ?";
            jct.update(
                    updateSql,
                    status,
                    new Timestamp(System.currentTimeMillis()), // 当前时间
                    orderId
            );

            // 3. 返回更新后的订单
            return jct.queryForObject(
                    selectSql,
                    new Object[]{orderId},
                    new BeanPropertyRowMapper<>(OrderEntity.class)
            );
        } catch (EmptyResultDataAccessException e) {
            throw new IllegalArgumentException("订单不存在: " + orderId);
        }
    }

    @Override
    public void save(OrderEntity order) {
        if (order.getId() == null) {
            orderEntityMapper.insert(order);
        } else {
            orderEntityMapper.updateByPrimaryKeySelective(order);
        }
    }

    @Override
    public OrderEntity updatePlannedDuration(Long orderId, int plannedDurationMinutes) {
        try {
            // 查询订单
            String sql = "SELECT * FROM charging_order WHERE id = ?";
            OrderEntity order = jct.queryForObject(sql, new BeanPropertyRowMapper<>(OrderEntity.class), orderId);
            
            if (order == null) {
                throw new EmptyResultDataAccessException("订单不存在: " + orderId, 1);
            }
            
            // 更新充电分钟数
            order.setChargingMinutes(plannedDurationMinutes);
            
            // 更新数据库
            String updateSql = "UPDATE charging_order SET charging_minutes = ? WHERE id = ?";
            jct.update(updateSql, plannedDurationMinutes, orderId);
            
            return order;
        } catch (Exception e) {
            throw new RuntimeException("更新计划充电时长失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public String getOrderIdByDevice(String deviceId) {
        try {
            // 查询已支付或充电中状态的订单
            String sql = "SELECT id FROM charging_order WHERE ele_code = ? AND status IN (1, 2) ORDER BY payment_time ASC LIMIT 1";
            List<Long> orderIds = jct.queryForList(sql, Long.class, deviceId);
            if(orderIds.size() > 0) {
                return "" + orderIds.get(0);
            }else {
                return null;
            }
        } catch (EmptyResultDataAccessException e) {
            return null;
        } catch (Exception e) {
            System.err.println("查询设备关联订单失败: deviceId=" + deviceId + ", error=" + e.getMessage());
            return null;
        }
    }


    public int UpdateOrderIdByDeviceId(String deviceId) {
        try {
            String sql = "update charging_order SET status = 9 where ele_code = ? AND status IN (1, 2)";
            return jct.update(sql,deviceId);

        } catch (Exception e) {
            System.err.println("更新退款订单失败: " + e.getMessage());
            return -1;
        }
    }

    // 供内部复用的订单查询方法
    private OrderEntity findOrderById(String orderId) {
        try {
            return jct.queryForObject(
                    "SELECT * FROM charging_order WHERE id = ?",
                    new BeanPropertyRowMapper<>(OrderEntity.class),
                    orderId
            );
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    // 状态验证逻辑封装
    private void validateOrderStatus(Integer status) {
        Set<Integer> validStatus = new HashSet<>(Arrays.asList(
                OrderEntity.STATUS_UNPAID,
                OrderEntity.STATUS_PAID_WAITING,
                OrderEntity.STATUS_CHARGING,
                OrderEntity.STATUS_COMPLETED,
                OrderEntity.STATUS_REFUNDED,
                OrderEntity.STATUS_TIMEOUT,
                OrderEntity.STATUS_CANCELLED
        ));
        if (!validStatus.contains(status)) {
            throw new IllegalArgumentException("无效的订单状态");
        }
    }

    @Override
    public List<String> getActiveDeviceIds() {
        try {
            // 查询所有活跃订单的设备ID（状态为0-已支付待充电、2-充电中）
            String sql = "SELECT DISTINCT ele_code FROM charging_order WHERE status IN (0, 2) AND is_deleted = 0 AND ele_code IS NOT NULL";
            return jct.queryForList(sql, String.class);
        } catch (Exception e) {
            System.err.println("查询活跃设备ID失败: " + e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public List<String> getRecentOrdersByDevice(String deviceId, int limit) {
        try {
            // 查询指定设备的最近订单，按创建时间倒序排列
            String sql = "SELECT id FROM charging_order WHERE ele_code = ? AND is_deleted = 0 ORDER BY payment_time DESC LIMIT ?";
            List<Long> orderIds = jct.queryForList(sql, Long.class, deviceId, limit);
            
            // 转换为字符串列表
            return orderIds.stream()
                    .map(String::valueOf)
                    .collect(java.util.stream.Collectors.toList());
        } catch (Exception e) {
            System.err.println("查询设备最近订单失败: deviceId=" + deviceId + ", error=" + e.getMessage());
            return new ArrayList<>();
        }
    }


    public int updateRefundOrder(ChargingOrder order) {
        try {
            String sql = "update charging_order SET status = ? , refund_amount = ? , refund_time = ? where order_id = ?";
            return jct.update(sql,order.getStatus(),order.getRefundAmount(),order.getRefundTime(),order.getOrderId());

        } catch (Exception e) {
            System.err.println("更新退款订单失败: " + e.getMessage());
            return -1;
        }
    }

    /*******************充电桩相关查询********************************/
    //更新心跳时间
    public int updateDeviceLastTime(String iccid) {
        String time=TimeUtils.getDateToString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss");
        try {
            String sql = "update charging_pile SET last_time = ? where iccid = ?";
            return jct.update(sql,time,iccid);

        } catch (Exception e) {
            System.err.println("更新心跳时间失败: " + e.getMessage());
            return -1;
        }
    }


    //查询
    public List<ChargingOrder> getDieIcc() {
        try {
            // 查询指定设备的最近订单，按创建时间倒序排列
            String sql = "SELECT t2.id id,t2.order_id orderId,t2.start_time startTime,t1.last_time endTime,t2.charging_minutes chargingMinutes,t2.prepay_amount PrepayAmount FROM charging_pile t1 LEFT JOIN charging_order t2 ON t1.iccid = t2.ele_code WHERE t1.iccid IS NOT NULL AND t2.status IN (2) AND t1.last_time < NOW() - INTERVAL 1  MINUTE";
            log.info("查询断电的订单sql: {}", sql);
            List<ChargingOrder> ChargingOrders =  jct.query(
                    sql.toString(),
                    new BeanPropertyRowMapper<>(ChargingOrder.class));

            // 转换为字符串列表
            return ChargingOrders;
        } catch (Exception e) {
            log.info("查询设备最近订单失败:  error=" + e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public List<StatisticsByMonth> getOrderStatisticsByMonth(String eleCode, String startDate, String endDate) {
        return orderEntityMapper.getOrderStatisticsByMonth(eleCode, startDate, endDate);
    }

    @Override
    public List<StatisticsByDay> getOrderStatisticsByDay(String eleCode, String Date) {
       return orderEntityMapper.getOrderStatisticsByDay(eleCode,Date);
    }

}